package se.webbzon.oschi01.worldobject;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;

import javax.media.j3d.Transform3D;

import se.webbzon.oschi01.worldobject.appearance.Appearance3D;

public abstract class WorldMovableGroup extends WorldMovableObject implements WorldGroup {
	
	// The group transform
	private final Transform3D groupTransform;
	
	// A collection of all children to this group
	private final Collection<WorldStaticObject> children;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new abstract WorldStaticGroup with a given appearance and
	 * a given set of registered methods. The 2D-depth of the instance is given
	 * by the input depth2D. **/
	public WorldMovableGroup(int registeredMethods, 
							int depth2d,
							Appearance3D appearance) {
		super(registeredMethods, depth2d, appearance);
		groupTransform = new Transform3D();
		children = new ArrayList<WorldStaticObject>();
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	@Override public void addInstance(WorldStaticObject instance) {
		instance.setGroup(this);
		children.add(instance);
	}
	
	@Override public void removeInstance(WorldStaticObject instance) {
		instance.setGroup(null);
		children.remove(instance);
	}
	
	@Override public Collection<WorldStaticObject> getInstances() {
		return Collections.unmodifiableCollection(children);
	}
	
	@Override public void getGroupTransform(Transform3D transform) {
		transform.set(groupTransform);
	}
	
	@Override public void transform(Transform3D transform) {
		transform.mul(groupTransform,transform);
	}
	
	/*============================================================
	Protected Methods
	============================================================*/
	
	@Override protected void refreshTransform(Transform3D transform, boolean appearance, boolean mask) {
		super.refreshTransform(transform,appearance,mask);
		final Transform3D t = new Transform3D();
		
		// Updates the group transform
		final WorldGroup group = getGroup();
		if (group != null) {
			group.getGroupTransform(t);
			groupTransform.mul(t,transform);
		} else
			groupTransform.set(transform);
		
		// Updates the transform of all children
		for (WorldStaticObject child : children) 
			child.refreshTransform(t,appearance,mask);
	}
	
	/*@Override protected void applyTransform(Transform3D transform) {
		super.applyTransform(transform);
		Transform3D t = new Transform3D();
		
		// Updates the group transform
		final WorldGroup group = getGroup();
		if (group != null) {
			group.getGroupTransform(t);
			groupTransform.mul(t,transform);
		} else
			groupTransform.set(transform);
		
		// Updates the transform of all children
		for (WorldStaticObject child : children) {
			child.getTransform(t);
			child.applyTransform(t);
		}
	}*/

}
